package com.ioi.filter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

/**
 * GlobalFilter 过滤器统一设置编码方式并记录请求响应日志
 *
 * @author LILIBO
 * @since 2024/5/24
 */
@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "charset", value = "UTF-8")})
public class GlobalFilter implements Filter {

    /**
     * Log4j日志记录
     */
    private static final Logger log = LogManager.getLogger(GlobalFilter.class);

    /**
     * 字符编码（默认：UTF-8）
     */
    private static String charset = "UTF-8";

    /**
     * 初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        charset = filterConfig.getInitParameter("charset");
    }

    /**
     * 执行过滤操作
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // 设置允许跨域的域，可以是具体的域名或者*（代表允许所有域）
        response.setHeader("Access-Control-Allow-Origin", "*");
        // 其他的CORS头部设置
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type");

        // 如果是OPTIONS请求，可能是CORS预检查，直接返回
        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(204); // 无内容
            return;
        }

        // 设置请求和响应的编码
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);

        long t1 = System.currentTimeMillis(); // 请求开始时间

        // 记录请求日志
        log.debug("----------------> [{}] {}", request.getMethod(), request.getRequestURI());

        // 获取JSON格式的请求数据
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), charset));
        StringBuilder jsonStr = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            jsonStr.append(line);
        }
        String jsonQ = jsonStr.toString();

        // 记录请求参数日志
        log.debug("request args: {}", jsonQ);

        // 将请求参数设置到作用域
        request.setAttribute("jsonQ", jsonQ);

        // 过滤器放行，将会调用对应的Servlet处理
        filterChain.doFilter(request, response);

        // 将响应结果从作用域中取出
        String jsonR = (String) request.getAttribute("jsonR");

        // 记录响应参数日志
        log.debug("response res: {}", jsonR == null ? "" : jsonR);

        long t2 = System.currentTimeMillis(); // 请求结束时间

        // 将接口处理结果响应给客户端
        if (jsonR != null) {
            PrintWriter out = response.getWriter();
            out.print(jsonR);
            out.flush();
            out.close();
        }

        // 记录响应日志
        log.debug("<---------------- [{}] {} (ms) ", response.getStatus(), (t2 - t1));
    }

    /**
     * 销毁
     */
    public void destroy() {
    }

}
